渗透测试

您所在的位置:网站首页 frida hook所有函数 渗透测试

渗透测试

2023-03-22 13:36| 来源: 网络整理| 查看: 265

该文章来自R0ysue书籍SO HOOk的总结

11.1 Native基础

11.1.1 NDK基础介绍:

1、安卓开发中除了java编译的dex由ART/Davilk虚拟机执行外、还存在C/C++编译的动态链接库文件由CPU执行

2、JAVA依赖SDK、C/C++需要NDK依赖库

3、NDK关键之一JNI、JNI可以完成在java调用C/C++函数。也可以在C/C++中调用java函数

4、JNI是JVM虚拟机的一部分

11.2.1 NDK开发

创建项目,会比不使用NDK的多cpp目录,cmaklists.txt用于指明C/C++代码如何编译。CPP用于存放native层相关代码

mainactivity代码如下

Static块中使用System.loadLibrary()来加载目标动态库文件到内存。最终生成的动态库文件名为lib+目标名+.so,这里就是libnatice-lab.so

native关键词修饰的方法即为JNI函数。函数内容由C/C++语言实现。使用crtl加左键进入函数主题

1、Native函数从Java的String变为JString

2、native函数名从java中的stringFromJNI变为Java_com_example_sohook_MainActivity_stringFromJNI。命名规则为java+报名+类名+方法名。是为了能够让Java层找到对应的C/C++函数

3、JNIEXPORT表示可被外部调用,即可导出函数

4、JNICALL是一个空声明

5、extern c表示以C命名规则,否则为C++,存在名称粉碎规则。可以使用c++filt进行还原

6、JNIENV*表示当前java线程的执行环境、通过这个JNIEnv* 指针,就可以对Java端的代码进行操作

7、如果native方法不是static的化,obj表示这个方法的类对象、否之为该方法的类

8、JNI层全局只有一个JAVAVM,在JNI_Oload函数参数中,Jni_onload函数在加载so文件后第一个运行,也是一定会运行的函数

JNIEXPORT jint JNI_OnLoad(JAVAVM* vm,void* reserved)

11.1.3 JNI函数逆向的基本流程

1、由C/C++编译生成的so文件存在lib目录下的相关架构中,使用Uname -a查看架构

2、JNI逆向过程中、首先需要找到在java层函数在Native层中对应的函数地址

3、Android系统为了快速找到JNI函数,起命名规则是固定的,可以使用objection 查看

memory list module 查看被加载到内存的模块

确认内存中由该模块,使用如下命令查看该模块的导出函数

memory list exports libnative-lib.so

函数对应的绝对地址为0x7133cd01dc,该地址在每次运行会变动,不变的是偏移量,

7、可以通过偏移量+基地址找到对应函数。

11.2 Frida native层Hook

11.2.1 native层Hook基础

在Frida脚本中实现native层Hook的API函数是interceptor.attch()函数,他的第一个参数是要Hook的函数地址、第二个参数是callbacks回调。回调中存在俩个函数:

onEnter()函数是在调用目标Hook函数前调用的处理函数、被Hook函数的参数以数组的形式放在args参数中。

onLeave()函数则是在被Hook的目标函数执行完成后执行的函数、被Hook的函数返回值就是retval

function hook_native(){ var addr = Module.getExportByName("libnative-lib.so", "Java_com_roysue_r0so_MainActivity_stringFromJNI"); Interceptor.attach(addr,{ onEnter:function(args){ console.log("jnienv pointer =>",args[0]) console.log("jobj pointer =>",args[1]) },onLeave:function(retval){ console.log("retval is =>",Java.vm.getEnv().getStringUtfChars(retval, null).readCString()) console.log("=================") } }) }

Naive Hook的要点就是Hook函数的首地址

11.2.2 Native层Hook-Hook函数首地址定位方法

0x01 导出函数

1、使用Module.getExportByName(moduleName|null,exportname)或者Module.findExportByName(moduleName|null,exportName)获取相应函数首地址

2、第一个参数为模块名、第二个参数是导出函数名,若第一个参数为null。则会在所有加载在内存中的模块搜索相应导出函数名。不为空则在该模块下

HookstringFromJNI函数代码如下

function hook_native(){ var addr = Module.getExportByName("libnative-lib.so", "Java_com_roysue_r0so_MainActivity_stringFromJNI"); Interceptor.attach(addr,{ onEnter:function(args){ console.log("jnienv pointer =>",args[0]) console.log("jobj pointer =>",args[1]) },onLeave:function(retval){ console.log("retval is =>",Java.vm.getEnv().getStringUtfChars(retval, null).readCString()) 使用frida提供的API函数java.vm.getenv函数获取当前线程的Jenv结构,使用GetStringUtfChars获取java的字符串对应的C字符串地址 最后通过readCString函数来读取内存中的C字符串 console.log("=================") } })

0x02非导出函数定位函数地址

1、通过Module.findBaseAddress(name)或者Module.getBaseAddress(name)俩个函数来获取模块基地址、使用add(offset)函数传入固定的偏移获取函数绝对地址

2、动态注册JNI函数和静态注册JNI函数。动态注册函数在naive层实现的函数名称不定、使用Jint RegisterNative(jclass clazz, const JNINativeMethod* methods,jint nMethods)

3、clazz参数使用FindClass JNI函数获取。

4、methods参数是一个数组、其中包含函数的签名信息和对应在native层的函数指针

4、nmethods参数是methods数组的数量

动态注册JNI函数

JNIEXPORT jstring JNICALL stringFromJNI3( JNIEnv* env, jobject /*this*/) { std::string hello = "Hello from C++ stringFromJNI3 r0ysue "; return env->NewStringUTF(hello.c_str()); } jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv * env; vm->GetEnv((void**)&env,JNI_VERSION_1_6); JNINativeMethod methods[] = { {"sI3","()Ljava/lang/String;",(void*)stringFromJNI3}, }; env->RegisterNatives(env->FindClass("com/roysue/r0so/MainActivity"),methods,1); return JNI_VERSION_1_6; }

此时再使用objection就无法找到该函数地址

4、偏移量的获取、通过HOok实现动态注册Registerxxx来获取动态注册后的stringFormJNI3函数

5、使用frida_hook_libart,该项目包含JNI函数和art函数的hook脚本,这里使用hook_RegisterNatives.js

hook到stringFromJNI3偏移量

最后写出hook对应JNI函数的脚本

function hook_native(){ var addr = Module.getExportByName("libnative-lib.so", "Java_com_roysue_r0so_MainActivity_stringFromJNI"); Interceptor.attach(addr,{ onEnter:function(args){ console.log("jnienv pointer =>",args[0]) console.log("jobj pointer =>",args[1]) },onLeave:function(retval){ console.log("retval is =>",Java.vm.getEnv().getStringUtfChars(retval, null).readCString()) console.log("=================") } }) } function hook_native3(){ var libnative_addr = Module.findBaseAddress('libnative-lib.so'); console.log("libnative_addr is => ",libnative_addr) var stringfromJNI3 = libnative_addr.add(0xf444); console.log("stringfromJNI3 address is =>",stringfromJNI3); Interceptor.attach(stringfromJNI3,{ onEnter:function(args){ console.log("jnienv pointer =>",args[0]) console.log("jobj pointer =>",args[1]) // console.log("jstring pointer=>",Java.vm.getEnv().getStringUtfChars(args[2], null).readCString() ) },onLeave:function(retval){ console.log("retval is =>",Java.vm.getEnv().getStringUtfChars(retval, null).readCString()) console.log("=================") } }) } function main(){ hook_native3() } setImmediate(main) function main(){ hook_native() } setImmediate(main)

运行结果



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3